<template>
  <div class="init-container">
    <div id="main">
      <div class="leftPanel">
        <o-flowchart
          ref="flowChat"
          :compBoxInfo="GT_compBoxInfo"
          :itemList="G_itemList"
          :toolbarConf="G_graphToolbarList"
          @on-canvas-click="onCanvasClick"
          @on-node-select="onNodeSelect"
          @on-edge-select="onEdgeSelect"
          @on-graph-editor-state="onGraphEditorState"
          @on-graph-toolbar-click="onGraphToolbarClick"
          @compBoxInfo="flowchartInit"
        >
          <template #openData>
            <open-graph-data
              ref="openData"
              :compBoxInfo="GT_compBoxInfo"
              :title="G_openDataTitle"
              @on-cell-dblclick="onCellDblclick"
            />
          </template>
        </o-flowchart>
      </div>
      <div class="rightPanel">
        <Split v-model="G_spliteProportion" mode="vertical">
          <div slot="top" class="r_top">
            <rule-attr ref="ruleAttr" :compBoxInfo="GT_compBoxInfo" />
          </div>
          <div slot="bottom" class="r_bottom">
            <node-attr ref="nodeAttr" :compBoxInfo="GT_compBoxInfo" />
          </div>
        </Split>
      </div>
    </div>
    <template v-for="modal of G_modalList">
      <component
        :is="modal.name"
        :key="modal.idx"
        :ref="'modal_' + modal.idx"
        v-bind="{ config: modal.params, idx: modal.idx }"
      ></component>
    </template>
  </div>
</template>
<script lang="ts">
import {
  T_srv,
  ts,
  ifs,
  Tsrv,
  T_ruleEditor,
  nodeAttr,
  ruleAttr,
  resources,
  cf,
  openDebug,
  beforeHandleNodeAndEdge,
  customGraphReg,
  itemList,
  graphToolbarList,
  N_oFlowchart,
  gridConf,
  vue
} from './config';

import openGraphData from './openGraphData/index.vue';

@T_srv.comp({
  components: {
    nodeAttr,
    ruleAttr,
    resources,
    openDebug,
    openGraphData
  }
})
export default class ruleEditor extends vue {
  // 父组件compBoxInfo
  @T_srv.prop({
    required: false,
    type: Object,
    default: null
  })
  compBoxInfo: ifs.I_compBoxInfo;

  @T_srv.ref('openData') GT_openData: any;

  private GT_compBox: ifs.I_compBox;

  private G_compID: string;

  private GT_compBoxInfo: ifs.I_compBoxInfo;

  private G_compName: string = 'ruleEditor';

  // 模组列表
  private G_modalList: Array<any> = [];

  private G_spliteProportion: number = cf.spliteProportion || 0.5;

  // modal编号
  private G_modalIdx: number = 0;

  // 逻辑处理类
  private G_editor: T_ruleEditor;

  private G_itemList: Array<object> = [];

  private G_graphToolbarList: Array<object> = [];

  private G_openDataTitle: string = '规则数据';

  private G_GridConf: any = undefined;

  @T_srv.ref(`flowChat`) G_flowChat: any;

  getThis(): any {
    return this;
  }

  created() {
    customGraphReg.customEdge.init();
    customGraphReg.customNode.init();
    customGraphReg.customLayout.init();
    this.G_GridConf = gridConf();
    this.G_spliteProportion = this.G_spliteProportion;
    this.G_itemList = itemList();
    this.G_graphToolbarList = graphToolbarList();

    this.G_compID = Tsrv.utils.getGUID();
    // 如果外部有传入组件信息
    if (Tsrv.utils.isEmpty(this.compBoxInfo)) {
      this.GT_compBox = new ts.T_compBox(this.G_compID); // 使用本地实例
    } else {
      this.G_compID = this.compBoxInfo.compID;
      this.GT_compBox = this.compBoxInfo.TcompBox;
    }
    this.GT_compBoxInfo = { compID: this.G_compID, TcompBox: this.GT_compBox };

    this.G_editor = new T_ruleEditor(this.GT_compBoxInfo);
    this.GT_compBox.addCompMergeName(
      this.G_compID,
      'TruleEditor',
      this.G_editor
    );
  }

  destroyed() {
    this.GT_compBox.removeCompMergeName(this.G_compID, 'ruleEditor');
    // 如果父组件传入的compBoxInfo则删除本文件产生的引用，反之是本组件产生的ID统一删除
    if (Tsrv.utils.isEmpty(this.compBoxInfo)) {
      this.GT_compBox.removeCompsWithCompID(this.G_compID);
    } else {
      this.GT_compBox.removeCompsMergeName(this.G_compID, [
        'TruleEdiror',
        'ruleEditor'
      ]);
    }

    Tsrv.compBox.removeCompMergeName(
      Tsrv.compBox.getDefGUID(), // 全局compBox
      'ruleEditor',
      'RuleEdirot'
    );
    this.G_editor = null;
  }

  mounted() {
    this.GT_compBox.addCompMergeName(this.G_compID, 'ruleEditor', this);
    // 最终应用组件向外抛出引用实例,以供应用间调用
    Tsrv.compBox.addCompMergeName(
      Tsrv.compBox.getDefGUID(), // 全局compBox
      'ruleEditor',
      this,
      'RuleEdirot'
    );
    this.$emit('compBoxInfo', this.GT_compBoxInfo);

    // this.GT_compBox.broadcast();
    this.$languageSetter.setLanguage('zh-CN');
  }

  flowchartInit(e) {
    // 函数注册
    this.G_flowChat.regFns([
      { name: 'beforeHandleNodeAndEdge', fn: beforeHandleNodeAndEdge },
      { name: 'before_new', fn: this.beforeNew },
      { name: 'after_save', fn: this.afterSave },
      { name: 'after_edit', fn: this.afterEdit },
      { name: 'after_audit', fn: this.afterAudit },
      { name: 'after_unAudit', fn: this.afterUnAudit }
    ]);
  }

  beforeNew(e: N_oFlowchart.I_toolbarClick): Promise<boolean> {
    const self = this;
    return new Promise(resolv => {
      if (self.G_editor.graphEditorState !== `none`) {
        this.saveDialog().then(s => {
          if (s === `err`) {
            resolv(false);
          } else {
            self.G_editor.initEdirot();
            // 清除画布
            e.Teditor.initGraph(); // 清除画布
            resolv(true);
          }
        });
      } else {
        self.G_editor.initEdirot();
        // 清除画布
        e.Teditor.initGraph(); // 清除画布
        resolv(true);
      }
    });
  }

  afterSave(e: N_oFlowchart.I_toolbarClick): Promise<boolean> {
    return new Promise(resove => {
      this.doSave(e.e).then(r => {
        if (r) {
          e.Teditor.GT_graphToolbar.setAuditBtnDisabled(true);
          e.Teditor.GT_graphToolbar.setBtnDisabled('wyRuleComp', false);
          e.Teditor.GT_graphToolbar.setBtnDisabled('wyRuleDebug', false);
          e.Teditor.GT_graphToolbar.setBtnDisabled('wyRuleIn', false);
          e.Teditor.GT_graphToolbar.setBtnDisabled('wyRuleOut', false);
        }
        resove(r);
      });
    });
  }

  afterEdit(e: N_oFlowchart.I_toolbarClick): Promise<boolean> {
    return new Promise(resove => {
      e.Teditor.GT_graphToolbar.setAuditBtnDisabled(true, 'all');
      e.Teditor.GT_graphToolbar.setBtnDisabled('wyRuleComp', true);
      e.Teditor.GT_graphToolbar.setBtnDisabled('wyRuleDebug', true);
      e.Teditor.GT_graphToolbar.setBtnDisabled('wyRuleIn', true);
      e.Teditor.GT_graphToolbar.setBtnDisabled('wyRuleOut', true);
      resove(true);
    });
  }

  afterAudit(e: N_oFlowchart.I_toolbarClick): Promise<boolean> {
    const that = this;
    return new Promise(resove => {
      that.doWebReq(`audit`).then(isSuccess => {
        !isSuccess && resove(false);
        e.Teditor.GT_graphToolbar.setBtnDisabled('wyRuleComp', true);
        e.Teditor.GT_graphToolbar.setBtnDisabled('wyRuleDebug', false);
        e.Teditor.GT_graphToolbar.setBtnDisabled('wyRuleIn', false);
        e.Teditor.GT_graphToolbar.setBtnDisabled('wyRuleOut', false);
        e.Teditor.GT_graphToolbar.setAuditBtnDisabled(isSuccess);
        e.Teditor.GT_graphToolbar.setBtnDisabled('edit', true);
        resove(true);
      });
    });
  }

  afterUnAudit(e: N_oFlowchart.I_toolbarClick): Promise<boolean> {
    const that = this;
    return new Promise(resove => {
      that.doWebReq(`cancelAudit`).then(isSuccess => {
        !isSuccess && resove(false);
        e.Teditor.GT_graphToolbar.setAuditBtnDisabled(!isSuccess);
        // 审核后不可以修改
        e.Teditor.GT_graphToolbar.setBtnDisabled('edit', false);
        e.Teditor.GT_graphToolbar.setBtnDisabled('wyRuleIn', true);
        e.Teditor.GT_graphToolbar.setBtnDisabled('wyRuleOut', true);
        e.Teditor.GT_graphToolbar.setBtnDisabled('wyRuleComp', false);
        resove(true);
      });
    });
  }

  // 打开一个窗口modual
  addModel(moduleName: string, params: any = {}) {
    this.G_modalList.push({
      name: moduleName,
      params,
      idx: ++this.G_modalIdx
    });
  }

  // 删除一个打开窗口module
  removeModel(moduleIdx: number) {
    const L_idx = this.G_modalList.findIndex(item => item.idx === moduleIdx);
    if (L_idx < 0) {
      return;
    }
    setTimeout(() => {
      this.G_modalList.splice(L_idx, 1);
    }, 500);
  }

  onNodeSelect(e) {
    this.GT_compBox.getCompMergeName(this.G_compID, `nodeAttr`).selectComp(e);
  }

  onEdgeSelect(e) {}

  async doSave(graph: any): Promise<boolean> {
    const self = this;
    self.G_editor.graph = graph;
    const [b, L_msg] = await self.G_editor.saveData();
    this.$msg(L_msg);
    return b;
  }

  onGraphEditorState(P_s: string) {
    this.G_editor.graphEditorState = P_s;
  }

  private saveDialog() {
    const self = this;
    return new Promise(resolve => {
      self.$Modal.confirm({
        title: '警告',
        content: '<p>是否保存?</p>',
        onOk: () => {
          // self.GT_compBox.getCompMergeName(this.G_compID).saveData();
          resolve(`saved`);
        },
        onCancel: () => {
          resolve(`cancel`);
        }
      });
    });
  }

  onGraphRemoveItem(item: any) {
    this.G_editor.removeNodeComp(item.id);
  }

  private openDebug() {
    const L_eventName = Tsrv.utils.getGUID(false);
    return new Promise(resolve => {
      this.addModel(`openDebug`, {
        compBoxInfo: this.GT_compBoxInfo,
        eventName: L_eventName,
        inArgs: this.G_editor.ruleAttr.inArg
      });
      this.$bus.$on(L_eventName, res => {
        this.$bus.$off(L_eventName);
        resolve(res);
      });
    });
  }

  // 定位显示switch节点连线
  showSwitchNodeEdge(edgeID: string, isShow: boolean) {
    this.G_flowChat.setEdgehoverStyles(edgeID, isShow);
  }

  private ruleComp() {
    if (!this.G_editor.ruleAttr.baseInfo.id) {
      this.$msg(`无规则数据可编译`);
      return;
    }
    this.doWebReq(`comp`);
  }

  // web请求
  async doWebReq(apiName: string, ruleNo?: string): Promise<boolean> {
    const [res, err] = await this.G_editor.ruleWebReq(apiName, ruleNo);
    if (res) {
      this.$msg(res.msg);
    } else {
      this.$msg(err);
    }
    if (apiName === 'isInPoolList') {
      return res.data['isInPoolList'];
    }
    return res.success;
  }

  onCellDblclick(e: any) {
    this.G_editor.setEditorData(e.row);
    this.G_flowChat.setToolbarBtnsDisabled('wyRuleDebug', false);
    if (e.row?.f_enabled) {
      this.G_flowChat.setToolbarBtnsDisabled('wyRuleComp', e.row.f_enabled);
      this.G_flowChat.setToolbarBtnsDisabled('audit', e.row.f_enabled);
      this.G_flowChat.setToolbarBtnsDisabled('unAudit', !e.row.f_enabled);
      this.G_flowChat.setToolbarBtnsDisabled('edit', e.row.f_enabled);
      this.G_flowChat.setToolbarBtnsDisabled('wyRuleIn', true);
      this.G_flowChat.setToolbarBtnsDisabled('wyRuleOut', true);
      this.doWebReq('isInPoolList').then(isSuccess => {
        this.G_flowChat.setToolbarBtnsDisabled('wyRuleIn', isSuccess);
        this.G_flowChat.setToolbarBtnsDisabled('wyRuleOut', !isSuccess);
      });
    }
  }

  onGraphToolbarClick(e: N_oFlowchart.I_toolbarClick) {
    switch (e.key) {
      case `open`:
        this.GT_openData.setDisplay(true);
        break;
      case `delete`:
        this.clearNodtAttr(e);
        break;

      case `wyRuleComp`:
        this.onGraphComp(e);
        break;
      case `wyRuleDebug`:
        this.onGraphDebug(e);
        break;
      case `wyRuleIn`:
        this.onGraphRuleIn(e);
        break;
      case `wyRuleOut`:
        this.onGraphRuleOut(e);
        break;

      default:
    }
  }

  // comp 编译脚本 debug 调试脚本  addPool 加入线程 removePool 移出线程 audit cancelAudit
  onGraphComp(e: N_oFlowchart.I_toolbarClick) {
    if (this.G_editor.graphEditorState !== `none`) {
      this.$msg(`请先保存`);
      this.saveDialog().then(s => {
        if (s === `save`) {
          this.ruleComp();
        }
      });
    } else {
      this.ruleComp();
    }
  }

  onGraphDebug(e: N_oFlowchart.I_toolbarClick) {
    // this.$msg(`功能未开放`);
    this.openDebug().then((res: any) => {
      this.removeModel(res.moduleID);
    });
  }

  onGraphRuleIn(e: N_oFlowchart.I_toolbarClick) {
    this.doWebReq(`addPool`).then(success => {
      success && this.G_flowChat.setToolbarBtnsDisabled('wyRuleIn', true);
      success && this.G_flowChat.setToolbarBtnsDisabled('wyRuleOut', false);
    });
  }

  onGraphRuleOut(e: N_oFlowchart.I_toolbarClick) {
    this.doWebReq(`removePool`).then(success => {
      success && this.G_flowChat.setToolbarBtnsDisabled('wyRuleIn', false);
      success && this.G_flowChat.setToolbarBtnsDisabled('wyRuleOut', true);
    });
  }

  onCanvasClick(e: any) {
    this.GT_compBox.getCompMergeName(this.G_compID, `nodeAttr`).selectComp({});
  }

  clearNodtAttr(e: N_oFlowchart.I_toolbarClick) {
    const L_nodeAttr = this.GT_compBox.getCompMergeName(
      this.G_compID,
      `nodeAttr`
    );
    const L_compData = L_nodeAttr.getCurrCompData();
    const idx: number = e.e.deletedItmes.findIndex(x => {
      return x.type === 'node' && x.id === L_compData.nodeID;
    });
    if (idx > -1) {
      L_nodeAttr.selectComp({});
    }
  }

  setGraphData(d: any) {
    this.G_flowChat.loadGraphData(d, true);
    this.G_flowChat.GT_editor.GT_graphToolbar.saveMode();
  }
}
</script>
<style scoped lang="scss">
#main {
  position: relative;
  height: 100%;
  width: 100%;
  margin: 0px;
  padding: 0px;

  background: #fff;

  .leftPanel {
    // flex-grow: 1;
    float: left;
    width: calc(100% - 400px);
    height: 100%;
    border: 1px solid #e3e3e8;
  }
  .rightPanel {
    float: right;
    position: relative;
    display: flex;
    width: 400px;
    height: 100%;
    flex-direction: column;
    border: 1px solid #e3e3e8;
    background: #fff;
    .r_top {
      // padding: 10px;
      height: 100%;
    }
    .r_bottom {
      // padding: 10px;
      height: 100%;
    }
  }
}
</style>
